package com.meizhuang.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.meizhuang.utils.support.HttpKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.tools.ant.taskdefs.Java;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StopWatch;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Aspect
@Configuration
@Slf4j
public class LoggerAspect {

    @Autowired
    private ObjectMapper mapper;

    @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.GetMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.PutMapping)" +
            "||@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {

        StopWatch watch = new StopWatch();
        watch.start();

        // 打印header
        HttpServletRequest request = HttpKit.getRequest();
        Enumeration names = request.getHeaderNames();
        StringBuilder builder = new StringBuilder("RequestHeader【");

        while(names.hasMoreElements()){
            String name = (String) names.nextElement();
            builder.append(String.format("%s:%s",name,request.getHeader(name)));
            builder.append("，");
        }
        builder.append("】");
        log.info(builder.toString());

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        List<Object> args = Stream.of(joinPoint.getArgs()).filter(item -> !(item instanceof HttpServletRequest
                || item instanceof HttpServletResponse
                || item instanceof MultipartFile
                || item instanceof  MultipartFile[])
        )
                .peek(c->System.out.println(c))
                .collect(Collectors.toList());

        String jsonReq = mapper.writeValueAsString(args);
        log.info("{}.{} [I]:{}", method.getDeclaringClass().getName(), method.getName(), jsonReq);
        Object proceed = joinPoint.proceed();
        watch.stop();
        String jsonRes = mapper.writeValueAsString(proceed);
        log.info("{}.{} [O]:{} ,耗时:{}ms", method.getDeclaringClass().getName(), method.getName(), jsonRes, watch.getTotalTimeMillis());
        return proceed;
    }

}
